package cn.bfay.lion.rest.service.impl;

import cn.bfay.cache.redis.RedisKeyBuilder;
import cn.bfay.cache.redis.RedisTime;
import cn.bfay.cache.redis.RedisUtils;
import cn.bfay.lion.rest.entity.UserProduct;
import cn.bfay.lion.rest.entity.WechatUser;
import cn.bfay.lion.rest.error.RestBusinessError;
import cn.bfay.lion.rest.manager.JingdongManager;
import cn.bfay.lion.rest.mapper.UserProductMapper;
import cn.bfay.lion.rest.mapper.WechatUserMapper;
import cn.bfay.lion.rest.redis.RedisKeyTemplate;
import cn.bfay.lion.rest.redis.RedisValueHelper;
import cn.bfay.lion.rest.service.WechatService;
import cn.bfay.lion.util.StringUtils;
import cn.bfay.web.exception.BizException;
import cn.bfay.web.util.WebUtils;
import cn.bfay.wechat.WechatCoreUtil;
import cn.bfay.wechat.model.WechatUserInfo;
import cn.bfay.wechat.model.menu.Button;
import cn.bfay.wechat.model.menu.Menu;
import cn.bfay.wechat.model.message.RequestMessage;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

import static cn.bfay.wechat.WechatCoreUtil.EVENT_TYPE_CLICK;
import static cn.bfay.wechat.WechatCoreUtil.EVENT_TYPE_SUBSCRIBE;
import static cn.bfay.wechat.WechatCoreUtil.EVENT_TYPE_TEMPLATESENDJOBFINISH;
import static cn.bfay.wechat.WechatCoreUtil.EVENT_TYPE_UNSUBSCRIBE;
import static cn.bfay.wechat.WechatCoreUtil.REQ_MESSAGE_TYPE_EVENT;
import static cn.bfay.wechat.WechatCoreUtil.REQ_MESSAGE_TYPE_LINK;
import static cn.bfay.wechat.WechatCoreUtil.REQ_MESSAGE_TYPE_TEXT;

/**
 * WechatServiceImpl.
 *
 * @author wangjiannan
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class WechatServiceImpl extends AbstractService implements WechatService {
    private static StringBuffer helpContent = new StringBuffer();

    static {
        helpContent.append("欢迎关注").append("\n\n");
        helpContent.append("1.京东APP复制商品链接").append("\n");
        helpContent.append("2.发送步骤1中链接到当前服务号").append("\n");
        helpContent.append("3.即可成功关注商品").append("\n\n");
        helpContent.append("<a href=\"https://www.wangjiannan.cn/page/watch-course\">点击查看详情操作</a>").append("\n");
        //helpContent.append("<a href=\"https://www.baidu.com/\">百度</a>").append("\n\n");
        //helpContent.append("回复\"?\"显示此帮助");
    }

    private final HttpServletRequest request;
    private final JingdongManager jingdongManager;
    private final WechatUserMapper wechatUserMapper;
    private final WechatCoreUtil wechatCoreUtil;
    private final UserProductMapper userProductMapper;

    @Override
    public String coreCheck() {
        return wechatCoreUtil.coreCheck(request);
    }

    @Override
    public String coreProcess() {
        //checkIp(request);

        RequestMessage requestMessage = wechatCoreUtil.coreProcess(request);
        //log.info("接收到请求内容={}", requestMessage.toString());

        // 发送方帐号（open_id）
        String fromUserName = requestMessage.getFromUserName();
        // 公众帐号
        String toUserName = requestMessage.getToUserName();
        // 消息类型
        String msgType = requestMessage.getMsgType();
        switch (msgType) {
            case REQ_MESSAGE_TYPE_EVENT: //a.事件推送
                String eventType = requestMessage.getEvent();
                switch (eventType) {
                    case EVENT_TYPE_SUBSCRIBE: // 订阅
                        //"谢谢您的关注！回复\"?\"获取帮助";
                        getWechatUser(fromUserName);
                        log.info("订阅通知,fromUserName={}", fromUserName);
                        return wechatCoreUtil.responseTextMessage(fromUserName, toUserName, helpContent.toString());
                    case EVENT_TYPE_UNSUBSCRIBE: // 取消订阅
                        log.info("取消订阅通知,fromUserName={}", fromUserName);
                        deleteAccount(fromUserName);
                        return "";
                    case EVENT_TYPE_TEMPLATESENDJOBFINISH:
                        log.info("模板消息推送结果通知");
                        return "";
                    case EVENT_TYPE_CLICK:
                        String eventKey = requestMessage.getEventKey();
                        if ("help".equalsIgnoreCase(eventKey)) {
                            return wechatCoreUtil.responseTextMessage(fromUserName, toUserName, helpContent.toString());
                        } else {
                            return wechatCoreUtil.responseTextMessage(fromUserName, toUserName, "无效请求!");
                        }
                    default:
                        return wechatCoreUtil.responseTextMessage(fromUserName, toUserName, "无效请求!");
                }
            case REQ_MESSAGE_TYPE_TEXT: // b.文本
                String content = requestMessage.getContent();
                if (content.equals("fdksjfakJKJK2NlKh94yHhJH2Ghkjk5g54gHJbD5zcxC")) {
                    createMenu();
                    return wechatCoreUtil.responseTextMessage(fromUserName, toUserName, "create menu success!");
                } else if (content.startsWith("http")) {
                    return wechatCoreUtil
                        .responseTextMessage(fromUserName, toUserName, addProduct(fromUserName, content));
                } else if ("?".equals(content) || "？".equals(content)) {
                    return wechatCoreUtil.responseTextMessage(fromUserName, toUserName, helpContent.toString());
                } else {
                    return wechatCoreUtil.responseTextMessage(fromUserName, toUserName, "无效请求!");
                }
            case REQ_MESSAGE_TYPE_LINK: //链接
                //String url = requestMessage.getUrl(); //消息链接
                //return wechatCoreManager.responseTextMessage(fromUserName, toUserName, addProduct(url));
                return wechatCoreUtil.responseTextMessage(fromUserName, toUserName, "无效请求!");
            default:
                return wechatCoreUtil.responseTextMessage(fromUserName, toUserName, "无效请求!");
        }
    }

    private void checkIp(HttpServletRequest request) {
        String ip = WebUtils.getRealIP(request);
        if (StringUtils.isEmpty(ip)) {
            throw new BizException(RestBusinessError.NOT_WECHAT_SERVER_ERROR);
        }
        List<String> ips = getCallbackIp();
        if (!ips.contains(ip)) {
            throw new BizException(RestBusinessError.NOT_WECHAT_SERVER_ERROR);
        }
    }

    private List<String> getCallbackIp() {
        String redisKey = RedisKeyBuilder.generateRedisKey(RedisKeyTemplate.WECHAT_SERVER_IP_TEMPLATE);
        TypeReference<List<String>> typeReference = new TypeReference<List<String>>() {
        };
        List<String> list = RedisUtils.getValue(redisKey, typeReference);
        if (list != null) {
            return list;
        }
        List<String> ips = wechatCoreUtil.getWechatServerIp(RedisValueHelper.getAccessToken());
        if (CollectionUtils.isEmpty(ips)) {
            throw new BizException(RestBusinessError.WECHAT_SERVER_IP_GET_ERROR);
        }
        RedisUtils.setValue(redisKey, ips, RedisTime.HNOUR * 6);
        return ips;
    }

    private String addProduct(String openid, String url) {
        try {
            int start = url.indexOf("product/");
            int end = url.indexOf(".html");
            if (start < 0 || end < 0) {
                throw new RuntimeException("商品url解析skuid错误");
            }
            String skuid = url.substring(url.indexOf("product/") + 8, url.indexOf(".html"));
            jingdongManager.addProductBySkuid(skuid);
            watchProduct(openid, skuid);
            return "关注成功";
        } catch (Exception e) {
            log.error("", e);
            return "操作失败";
        }
    }


    private void deleteAccount(String openid) {
        WechatUser wechatUser = new WechatUser();
        wechatUser.setOpenid(openid);
        wechatUser.setState(0);
        wechatUserMapper.updateById(wechatUser);

        UserProduct userProduct = new UserProduct();
        userProduct.setMark((byte) 0);
        userProduct.setNoticePrice(0.00);
        userProductMapper.update(userProduct, new QueryWrapper<UserProduct>().lambda()
            .eq(UserProduct::getOpenid, openid));
    }

    private void getWechatUser(String openid) {
        WechatUserInfo wechatUserInfo = wechatCoreUtil.getUserInfo(RedisValueHelper.getAccessToken(), openid);
        WechatUser wechatUser = new WechatUser();
        BeanUtils.copyProperties(wechatUserInfo, wechatUser); //source, target
        WechatUser oldWechatUser = wechatUserMapper.selectById(openid);
        if (oldWechatUser == null) {
            wechatUser.setState(1);
            wechatUserMapper.insert(wechatUser);
        } else {
            wechatUser.setState(1);
            wechatUserMapper.updateById(wechatUser);
        }
    }

    private void createMenu() {
        Button button1 = new Button();
        button1.setName("商品");
        button1.setType("view");
        button1.setUrl(wechatCoreUtil.generateAuthUrl("https://www.wangjiannan.cn/page/product-oauth"));

        Button button2 = new Button();
        button2.setName("关注");
        button2.setType("view");
        button2.setUrl(wechatCoreUtil.generateAuthUrl("https://www.wangjiannan.cn/page/watch-oauth"));

        Button button3 = new Button();
        button3.setName("帮助");
        button3.setType("click");
        button3.setKey("help");

        Button[] buttons = new Button[]{button1, button2, button3};
        Menu menu = new Menu();
        menu.setButton(buttons);
        wechatCoreUtil.createMenu(RedisValueHelper.getAccessToken(), menu);
    }
}
